* Sampleapp

This is a barebones sample application for a multi-module, multi-bundle apache karaf web application.

Intended to make it simple to start a new webapp.

The application database has a table "accounts" listing the users that are allowed to log into the database.  It also has some tables supporting a simple counter application (the increment step size for the counter for each logged in user, and the current count for each user).

Highlights of the app:
 - Uses the [[https://docs.osgi.org/specification/osgi.cmpn/7.0.0/service.http.whiteboard.html][OSGi HTTP whiteboard]] to register servlets as services and give them a web context and paths
 - [[https://www.postgresql.org][react.js]] frontend, using [[https://redux.js.org][redux]] for state management (set up using [[https://redux-toolkit.js.org][redux-toolkit]]) and [[https://redux-saga.js.org][saga]] for asynchonous REST communication and asynchronous redux state logic
 - [[https://redux-saga.js.org][bootstrap v4]] styling of the frontend
 - [[https://en.wikipedia.org/wiki/Internationalization_and_localization][i18n/l11n]] support (using redux on the frontend and [[https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/ResourceBundle.html][Java resource bundles]] on the backend) with English and Norwegian as the languages
 - [[https://en.wikipedia.org/wiki/Jakarta_RESTful_Web_Services][JAX-RS]] REST Service support provided by [[https://eclipse-ee4j.github.io/jersey/][eclipse jersey]]
 - authentication and authorization provided by [[https://shiro.apache.org][apache shiro]] (implemented in [[https://github.com/steinarb/authservice][authservice]], but in theory anything that provides a [[https://shiro.apache.org/realm.html][shiro Realm]] as an OSGi service and provides a shiro role named sampleappuser can give access to the application)
 - JDBC configuration and setup using [[https://ops4j1.jira.com/wiki/spaces/PAXJDBC/pages/61767710/Create+DataSource+from+config][PAX JDBC config]] (provides a Datasource OSGi service using configuration only and no code needed)
 - Database migration support provided by [[https://liquibase.org][liquibase]] with sample database setups for [[https://db.apache.org/derby/][apache derby]] and [[https://www.postgresql.org][PostgreSQL]]

All user information, outside of the username, i.e. full name, email, comes from an injected OSGi service of type [[https://www.javadoc.io/doc/no.priv.bang.osgiservice/osgiservice/latest/no/priv/bang/osgiservice/users/UserManagementService.html][UserManagementService]] provided by the [[https://github.com/steinarb/authservice][authservice]].

The username/password combinations of users in the test db version of authservice, are:
| username | password  | authorized for sampleapp |
|----------+-----------+--------------------------|
| jad      | 1ad       | yes                      |
| jod      | johnnyBoi | no                       |

** Development status
[[https://github.com/steinarb/ratatoskr/actions/workflows/ratatoskr-maven-ci-build.yml][file:https://github.com/steinarb/ratatoskr/actions/workflows/ratatoskr-maven-ci-build.yml/badge.svg]]
[[https://coveralls.io/github/badges/shields?branch=master][file:https://coveralls.io/repos/github/badges/shields/badge.svg?branch=master]]
[[https://sonarcloud.io/summary/new_code?id=steinarb_ratatoskr][file:https://sonarcloud.io/api/project_badges/measure?project=steinarb_ratatoskr&metric=alert_status#.svg]]

[[https://sonarcloud.io/summary/new_code?id=steinarb_ratatoskr][file:https://sonarcloud.io/images/project_badges/sonarcloud-white.svg]]

[[https://sonarcloud.io/summary/new_code?id=steinarb_ratatoskr][file:https://sonarcloud.io/api/project_badges/measure?project=steinarb_ratatoskr&metric=sqale_index#.svg]]
[[https://sonarcloud.io/summary/new_code?id=steinarb_ratatoskr][file:https://sonarcloud.io/api/project_badges/measure?project=steinarb_ratatoskr&metric=coverage#.svg]]
[[https://sonarcloud.io/summary/new_code?id=steinarb_ratatoskr][file:https://sonarcloud.io/api/project_badges/measure?project=steinarb_ratatoskr&metric=ncloc#.svg]]
[[https://sonarcloud.io/summary/new_code?id=steinarb_ratatoskr][file:https://sonarcloud.io/api/project_badges/measure?project=steinarb_ratatoskr&metric=code_smells#.svg]]
[[https://sonarcloud.io/summary/new_code?id=steinarb_ratatoskr][file:https://sonarcloud.io/api/project_badges/measure?project=steinarb_ratatoskr&metric=sqale_rating#.svg]]
[[https://sonarcloud.io/summary/new_code?id=steinarb_ratatoskr][file:https://sonarcloud.io/api/project_badges/measure?project=steinarb_ratatoskr&metric=security_rating#.svg]]
[[https://sonarcloud.io/summary/new_code?id=steinarb_ratatoskr][file:https://sonarcloud.io/api/project_badges/measure?project=steinarb_ratatoskr&metric=bugs#.svg]]
[[https://sonarcloud.io/summary/new_code?id=steinarb_ratatoskr][file:https://sonarcloud.io/api/project_badges/measure?project=steinarb_ratatoskr&metric=vulnerabilities#.svg]]
[[https://sonarcloud.io/summary/new_code?id=steinarb_ratatoskr][file:https://sonarcloud.io/api/project_badges/measure?project=steinarb_ratatoskr&metric=duplicated_lines_density#.svg]]
[[https://sonarcloud.io/summary/new_code?id=steinarb_ratatoskr][file:https://sonarcloud.io/api/project_badges/measure?project=steinarb_ratatoskr&metric=reliability_rating#.svg]]

** Installing the sample application

First clone and build the sample application:
#+begin_example
  mkdir -p ~/git/
  cd ~/git/
  git clone https://github.com/steinarb/ratatoskr.git
  cd ~/git/ratatoskr/
  mvn install
#+end_example

Then give the following commands to the karaf console:
#+BEGIN_EXAMPLE
  feature:repo-add mvn:no.priv.bang.ratatoskr/karaf/LATEST/xml/features
  feature:install ratatoskr-with-derby
#+END_EXAMPLE

Then:
 1. open http://localhost:8181/ratatoskr in a web browser
 2. log in as user "jad" with password "1ad"
 3. click on counter and use "-" and "+" to change the value
 4. try editing the step size, wait a few seconds and then observe that "+" and "-" change the value with the step size
 5. Navigate to the top page and log out
 6. Log in as user "jod" with password "johnnyBoi" and observe that you end in a "not authorized page" (the user exists but do not have the role of the app)
 7. Log out and log back in as user "jad", navigate to the "counter" page, and observe that the count is like you left it (the count is persisted in the database)

** Creating a new application based on the sample app

Using the [[https://maven.apache.org/archetype/maven-archetype-plugin/i][maven archetype plugin]] to adapt the sample project to a new project is simpler than hand editing the sample project and moving all packages and module names, but it doesn't take you all the way (it doesn't rename Java classes and doesn't fix up the shiro.ini files).

To create a new project called "mynewapp":
 1. First clone the sample project and create an archetype from it (it's best to create an archetype from a fresh clone, because then the archetype won't contain unnecessary files like IDE config files and binary files from the build)
    #+begin_example
      cd /tmp
      git clone https://github.com/steinarb/ratatoskr.git
      cd ratatoskr
      mvn archetype:create-from-project -Darchetype.filteredExtensions=java
      cd target/generated-sources/archetype/
      mvn install
    #+end_example
 2. Create the new project from the archetype (the -DgroupId, -DartifactId, and -Dversion arguments are the GAV values of the new project)
    #+begin_example
      mkdir -p ~/git/
      cd ~/git/
      mvn archetype:generate -DarchetypeCatalog=local -DarchetypeGroupId=no.priv.bang.ratatoskr -DarchetypeArtifactId=ratatoskr-archetype -DgroupId=com.mycompany.mynewapp -DartifactId=mynewapp -Dversion=1.0.0-SNAPSHOT -DinteractiveMode=false
    #+end_example
 3. Fix the groupId for a karaf feature file dependency in the integration test maven module, because this dependency isn't handled by the archetype project generator:
    #+begin_example
      cd ~/git/mynewapp/
      sed -i 's/no\.priv\.bang\.ratatoskr/com.mycompany.mynewapp/gI' */pom.xml
    #+end_example
 4. Fix up some files that aren't handled by the archetype filtering (don't know why everything in the pom files aren't filtered)
    #+begin_example
      sed -i 's/ratatoskr/mynewapp/g' */src/main/resources/shiro.ini
      sed -i 's/ratatoskr/mynewapp/g' */src/test/resources/test.shiro.ini
      sed -i 's/ratatoskr/mynewapp/gI' */pom.xml
      find . -name \*.js | xargs sed -i 's/ratatoskr/mynewapp/g'
    #+end_example
 5. Add a .gitignore file (there is a bug in maven-resources-plugin that excludes this file from archetypes):
    #+begin_example
      ,*.iml
      ,*.log
      .classpath
      .idea/
      .project
      .settings/
      /.metadata/
      /TAGS
      node_modules/
      target/
    #+end_example
 6. Test build the project with "mvn install" (it should build without any errors)
    #+begin_example
      cd ~/git/mynewapp/
      mvn install
    #+end_example
 7. Open the java maven modules of the mynewapp project, in a Java IDE (eclipse or IntelliJ), and use the refactoring of the IDE to rename classes with names starting with "Ratatoskr" into classes starting with "Mynewapp" (this is the step that the archetype can't handle, but at least the classes are already in packages they are supposed to be in for the new application)
 8. Build mynewapp from the top with "mvn clean install" ("clean" is to get rid of .class files with the old names)
    #+begin_example
      cd ~/git/mynewapp/
      mvn clean install
    #+end_example
 9. Correct some Java class member names that hasn't been touched by the renaming (OSGi service injection setter and constants):
    #+begin_example
      find . -name \*.java | xargs sed -i 's/Ratatoskr/Mynewapp/g'
      find . -name \*.java | xargs sed -i 's/RATATOSKR/MYNEWAPP/g'
    #+end_example
 10. Install mynewapp in a karaf instance
     #+begin_example
       feature:repo-add mvn:com.mycompany.mynewapp/karaf/LATEST/xml/features
       feature:install mynewapp-with-derby
     #+end_example
 11. Verify that the application is running on http://localhost:8181/mynewapp

** Configuring a new default locale

Out of the box, the sample application supports two locales: nb_NO (Norwegian bokmål) and en_GB (UK English).

The locale texts are provided by a Java resource bundle, and new languages can be added by adding them to the bundle and to the available locales returned by the RatatoskrService.

The default locale is nb_NO.

It is possible to persistently configuring the default locale to en_GB with the following commands in the karaf console command line:
#+begin_example
  config:edit no.priv.bang.ratatoskr.backend.RatatoskrServiceProvider
  config:property-set defaultlocale en_GB
  config:update
#+end_example

/Note/! The name of the config file will change when the package name and classname of the class changes in a new application based on this one, so adjust the command example accordingly.
** License

This software is licensed with the Apache License v2.  See the file LICENSE for details.
